package cz.pecinovsky.česky.oopnz._134_;
//Příliš žluťoučký kůň úpěl ďábelské ódy

import cz.pecinovsky.česky.oopnz.správce.SprávcePlátna;

import cz.pecinovsky.česky.oopnz.utility.IO;


import static cz.pecinovsky.česky.oopnz._134_.ITovárnaOkruhů_140_.ITovárnaOkruhů;
import static cz.pecinovsky.česky.oopnz._134_.Okruh_134_        .Okruh;
import static cz.pecinovsky.česky.oopnz._134_.PoleCesty_134_    .PoleCesty;
import static cz.pecinovsky.česky.oopnz._134_.StavitelOkruhů_134_ .StavitelOkruhů;


//import static cz.pecinovsky.česky.oopnz._134_.TovárnaNaKola_140_.TovárnaNaKola;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ Konec ignorovaného počátečního textu +++++
//%I+
//
//import cz.pecinovsky.česky.oopnz.správceplátna.SprávcePlátna;
//%I-

import cz.pecinovsky.česky.oopnz.utility.Barva;
import cz.pecinovsky.česky.oopnz.utility.Pozice;
import cz.pecinovsky.česky.oopnz.utility.Směr8;
//%X+ xxxxx Začátek přeskakovaného textu xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class TovárnaNaKola_140_
{    private TovárnaNaKola_140_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- Konec přeskakovaného textu -----


/*******************************************************************************
 * Instance třídy {@code TovárnaNaKola} představují továrny, které jsou schopny
 * na požádání "vyrobit" obdélníkový okruh.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
public class TovárnaNaKola implements ITovárnaOkruhů
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Správce plátna, na němž bude cesta zobrazena. */
    SprávcePlátna SP = SprávcePlátna.getInstance();



//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Políčková šířka okruhů, tj. počet zabraných sloupců. */
    private final int sloupců;

    /** Políčková výška okruhů, tj. počet zabraných řádků. */
    private final int řádků;

    /** Směr, která se vyráží z výchozí pozice. */
    private final Směr8 směr;



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

     /** Implicitní barva vytvářených okruhů. */
     private Barva implicitníBarva = Barva.ČERNÁ;



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří nový obdélníkový okruh se zadanou počtem polí na šířku i výšku
     * a se zadaným směrem, jímž se vyráží z vvýchozí pozice, která je vždy
     * v levém horním rohu vytvořeného okruhu.
     * 
     * @param sloupců Políčková šířka okruhů, tj. počet zabraných sloupců
     * @param řádků   Políčková výška okruhů, tj. počet zabraných řádků
     * @param směr    Směr, která se vyráží z výchozí pozice, má smysl pouze
     *                {@link Směr8.VÝCHOD} nebo {@link Směr8.JIH}
     */
    public TovárnaNaKola(int sloupců, int řádků, Směr8 směr)
    {
        this.sloupců = sloupců;
        this.řádků   = řádků;
        this.směr    = směr;
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================

    /***************************************************************************
     * Nastaví implicitní barvu vytvářených okruhů.
     *
     * @param barva Nastavovaná implicitní barva
     * @return Dříve nastavená implicitní barva
     */
    @Override
    public Barva setImplicitníBarva(Barva barva)
    {
        Barva stará     = implicitníBarva;
        implicitníBarva = barva;
        return stará;
    }


    /***************************************************************************
     * Vrátí počet sloupců, které daný okruh zabere.
     *
     * @return Počet sloupců okruhu
     */
    public int getSloupců()
    {
        return sloupců;
    }


    /***************************************************************************
     * Vrátí počet řádků, které daný okruh zabere.
     *
     * @return Počet řádků okruhu
     */
    public int getŘádků()
    {
        return řádků;
    }



//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Vytvoří okruh implicitní barvy se startovním polem na zadané pozici.
     *
     * @param startPozice Pozice startovního pole vytvářeného okruhu
     * @return Vytvořený okruh
     */
    @Override
    public Okruh vytvořOkruh(Pozice startPozice)
    {
        return vytvořOkruh(startPozice, implicitníBarva);
    }


    /***************************************************************************
     * Vytvoří okruh zadané barvy se startovním polem na zadané pozici.
     *
     * @param startPozice Pozice startovního pole vytvářeného okruhu
     * @param barva       Barva vytvářeného okruhu
     * @return Vytvořený okruh
     */
    @Override
    public Okruh vytvořOkruh(Pozice startPozice, Barva barva)
    {
        StavitelOkruhů stavitel = new StavitelOkruhů(startPozice, barva);
        stavitel.zahajNa(směr);
        if (směr == Směr8.JIH) {
            dotvořOkruh(stavitel, řádků-1, sloupců, řádků, sloupců-1);
        }
        else {
            dotvořOkruh(stavitel, sloupců-1, řádků, sloupců, řádků-1);
        }
        return stavitel.getOkruh();
    }


    /***************************************************************************
     * Prostřednictvím zadaného stavitele dotvoří okruh zadaných rozměrů
     * přičemž směr pohybu po vytvářeném okruhu je odvozen z atributu
     * {@link #směr}.
     *
     * @param stavitel Stavitel, který začal stavět zadaný okruh
     * @param rozměry  Počet průběžných polí, která se mají položit
     *                 v jednotlivých směrech
     */
    private void dotvořOkruh(StavitelOkruhů stavitel, int... rozměry)
    {
        if (rozměry.length != 4) {
            throw new IllegalArgumentException(
                    "\nMusí být zadány právě čtyři rozměry");
        }
        Směr8 aktSměr = směr;
        for (int rozměr : rozměry) {
            for (int i=1;   i < rozměr;   i++) {
                stavitel.pokračujNa(aktSměr);
            }
            if (směr == Směr8.JIH) {
                aktSměr = aktSměr.vlevoVbok();
            } else {
                aktSměr = aktSměr.vpravoVbok();
            }
        }
        //Musím směr otočit zpět, protože ještě nezahýbám
        if (směr == Směr8.JIH) {
            aktSměr = aktSměr.vpravoVbok();
        } else {
            aktSměr = aktSměr.vlevoVbok();
        }
        stavitel.uzavřiNa(aktSměr);
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTY A METODA MAIN =======================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        TovárnaNaKola inst = new TovárnaNaKola();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}

//%%-  ----- Začátek ignorovaného závěrečného textu -----
////////////////////////////////////////////////////////////////////////////////
//== TESTY A METODA MAIN =======================================================
//Není-li třída testovací, následující dvě metody se smažou

    /***************************************************************************
     * Testovací metoda.
     */
    public static void test()
    {
        Směr8 směr = Směr8.JIH;
        SprávcePlátna SP = SprávcePlátna.getInstance();

        for (int i=2;   i <= 6;   i++)  {
            TovárnaNaKola tk = new TovárnaNaKola(i, i, směr);
            Okruh o = tk.vytvořOkruh(new Pozice(0,0), Barva.ČERNÁ);
            SP.přidej(o);
            IO.zpráva("Vytvořen okruh \n" + o);
            SP.odstraň(o);
            směr = (směr  == Směr8.JIH)  ?  Směr8.VÝCHOD
                                         :  Směr8.JIH;
        }
        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main( String[] args )  { test(); }
}
